"""
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    created by siyi.chen on '20/11/2024'
    comment: cariabot自定义逻辑
"""
import base64
from datetime import datetime
import filetype

from project.core.exception import BizError
from project.micro_service.vision import Vision
from project.micro_service.zeus import Zeus
from project.model.api_model import InterCariabot
from project.model.basic import Operator
from project.model.database.flow import Flow
from project.model.database.cariabot import Cariabot as CariabotModel, CariabotColumn, CariabotColumnService, CariabotColumnView, CariabotView, Organization
from project.model.basic import Device
from project.middleware.oss import Oss


class CariabotService:

    @staticmethod
    async def get_cariabot_card_list(session, operator: Operator) -> list:
        """ 获取cariabot卡片列表
        :param session:
        :param operator: 当前用户
        :return:
        """
        # 获取卡片列表
        data = await Vision.get_card_list_with_org(operator.organization_code)

        return data

    @staticmethod
    async def get_cariabot_info(session, operator: Operator):
        """ 获取cariabot自定义信息
        :param session: 数据库会话
        :param operator: 当前用户
        :return:
        """
        # 获取该机构下的cariabot信息
        cariabot_model = await CariabotModel.fetch_one(session, wheres=(CariabotModel.organization_code == operator.organization_code, ~CariabotModel.is_deleted))
        if not cariabot_model:
            return {}
        column_data = []
        # 获取cariabot栏目信息
        column_list = await CariabotColumn.fetch_all(session, wheres=(CariabotColumn.cariabot_id == cariabot_model.id, ~CariabotColumn.is_deleted), orders=CariabotColumn.rank)
        for item in column_list:
            column = CariabotColumnView()
            column.id = item.id
            column.name = item.name
            column.icon_checked = item.icon_checked
            column.icon_unchecked = item.icon_unchecked
            column.column_type = item.column_type
            column.tags = item.tags
            column.preamble = item.preamble
            column.human_phone = item.human_phone
            column.human_nickname = item.human_nickname
            column.h5_url = item.h5_url
            service_data = []
            if item.column_type == 'flow' or item.column_type == 'card' or item.column_type == 'external' or item.column_type == 'shortcut' or item.column_type == 'voip':
                # 获取cariabot栏目服务信息
                service_list = await CariabotColumnService.fetch_all(session, wheres=(CariabotColumnService.column_id == item.id, ~CariabotColumnService.is_deleted))
                codes = [v.code for v in service_list]
                if item.column_type == 'flow' or item.column_type == 'shortcut':
                    code_image_map = {v.code: v.image for v in service_list}
                    flow_list = await Flow.fetch_all(session, wheres=(Flow.code.in_(codes), ~Flow.is_deleted))
                    service_data = [{'code': v.code, 'name': v.name, 'image': code_image_map.get(v.code)} for v in flow_list]
                elif item.column_type == 'card':
                    code_image_map = {v.code: v.image for v in service_list}
                    card_data = await Vision.get_cards_with_codes(organization_code=operator.organization_code, codes=codes)
                    service_data = [{'code': v.get('recognize_txt'), 'image': code_image_map.get(v.get('recognize_txt'))} for v in card_data]
                elif item.column_type == 'external':
                    service_data = [v.dict('name','url','image','preamble') for v in service_list]
                elif item.column_type == 'voip':
                    service_data = [v.dict('name','code','rank') for v in service_list]
                else:
                    service_data = []
            column.service_list = service_data
            column_data.append(column)
        # 组装返回数据
        view_data = CariabotView()
        view_data.background_image = cariabot_model.background_image
        view_data.digital_human_id = cariabot_model.digital_human_id
        view_data.digital_human_image = cariabot_model.digital_human_image
        view_data.awaken = cariabot_model.awaken
        view_data.voice_icon = cariabot_model.voice_icon
        view_data.columns = column_data
        return view_data

    @staticmethod
    async def save_cariabot_info(session, organization_code, inter_cariabot: InterCariabot):
        """ 保存cariabot自定义信息
        :param session: 数据库会话
        :param organization_code: 机构编号
        :param inter_cariabot: 自定义信息
        :return:
        """
        # 保存cariabot自定义信息
        cariabot_model = await CariabotModel.create_modify(session,
                                                           wheres=(CariabotModel.organization_code == organization_code, ~CariabotModel.is_deleted),
                                                           organization_code=organization_code,
                                                           background_image=inter_cariabot.background_image,
                                                           digital_human_id=inter_cariabot.digital_human_id,
                                                           digital_human_image=inter_cariabot.digital_human_image,
                                                           awaken=inter_cariabot.awaken,
                                                           voice_icon=inter_cariabot.voice_icon,
                                                           commit=False)
        if not cariabot_model:
            raise BizError('保存失败')

        # 将该机构下的服务流程和卡片全部删除，方便顺序插入
        columns = await CariabotColumn.fetch_all(session, wheres=(CariabotColumn.cariabot_id == cariabot_model.id, ~CariabotColumn.is_deleted))
        ids = [v.id for v in columns]
        services = await CariabotColumnService.fetch_all(session, wheres=(CariabotColumnService.column_id.in_(ids), ~CariabotColumnService.is_deleted))
        for service in services:
            service.is_deleted = True

        # 解析 columns
        rank = 0
        for item in inter_cariabot.columns:
            if item.custom_icon_checked and item.custom_icon_unchecked:
                oss = Oss()
                name = datetime.now().strftime('%Y%m%d%H%M%S%f')
                checked_content = base64.b64decode(item.custom_icon_checked)
                unchecked_content = base64.b64decode(item.custom_icon_unchecked)
                checked_kind = filetype.guess(checked_content)
                unchecked_kind = filetype.guess(unchecked_content)
                if not checked_kind or not unchecked_kind:
                    raise BizError('上传失败，请上传图片格式文件')
                checked_url = oss.upload_file(object_name=f'cariabot/icon_custom/checked_{name}.{checked_kind.extension}', bytes_file=checked_content)
                unchecked_url = oss.upload_file(object_name=f'cariabot/icon_custom/unchecked_{name}.{unchecked_kind.extension}', bytes_file=unchecked_content)
                item.icon_checked = checked_url
                item.icon_unchecked = unchecked_url

            cariabot_column = await CariabotColumn.create_modify(session,
                                                                 wheres=(CariabotColumn.id == item.id, ~CariabotColumn.is_deleted),
                                                                 cariabot_id=cariabot_model.id,
                                                                 name=item.name,
                                                                 icon_checked=item.icon_checked,
                                                                 icon_unchecked=item.icon_unchecked,
                                                                 column_type=item.column_type,
                                                                 tags=item.tags,
                                                                 preamble=item.preamble,
                                                                 human_phone=item.human_phone,
                                                                 human_nickname=item.human_nickname,
                                                                 rank=rank,
                                                                 h5_url=item.h5_url,
                                                                 commit=False)
            # 解析flow_list
            for s in item.service_list:
                if s.custom_icon:
                    oss = Oss()
                    name = datetime.now().strftime('%Y%m%d%H%M%S%f')
                    content = base64.b64decode(s.custom_icon)
                    kind = filetype.guess(content)
                    if not kind:
                        raise BizError('上传失败，请上传图片格式文件')
                    url = oss.upload_file(object_name=f'cariabot/icon_custom/{name}.{kind.extension}', bytes_file=content)
                    s.image = url
                await CariabotColumnService.create_modify(
                    session,
                    column_id=cariabot_column.id,
                    code=s.code,
                    name=s.name,
                    image=s.image,
                    url=s.url,
                    preamble=s.preamble,
                    commit=False
                )
            rank += 1

        await session.commit()

    @staticmethod
    async def do_cariabot_column_delete(session, organization_code, id):
        """ 删除栏目
        :param session: 数据库会话
        :param organization_code: 机构编号
        :param id: 栏目id
        :return:
        """
        # 获取该机构下的cariabot信息
        cariabot_model = await CariabotModel.fetch_one(session, wheres=(CariabotModel.organization_code == organization_code, ~CariabotModel.is_deleted))
        if not cariabot_model:
            raise BizError('删除失败，该机构下的cariabot信息不存在')
        # 获取栏目信息
        column = await CariabotColumn.fetch_one(session, wheres=(CariabotColumn.cariabot_id == cariabot_model.id, CariabotColumn.id == id, ~CariabotColumn.is_deleted))
        if not column:
            raise BizError('删除失败，该栏目不存在')
        # 删除栏目下的服务内容
        services = await CariabotColumnService.fetch_all(session, wheres=(CariabotColumnService.column_id == id, ~CariabotColumn.is_deleted))
        for service in services:
            service.is_deleted = True

        column.is_deleted = True

        await session.commit()

    @staticmethod
    async def get_cariabot_external_list(session, device: Device, sidebar_id=0):
        """ 得到设备第三方模块列表
        :param session:
        :param device:
        :param sidebar_id:
        :return:
        """
        wheres = list()
        if sidebar_id:
            wheres.append(CariabotColumnService.column_id == sidebar_id)
        else:
            cariabot = await CariabotModel.fetch_one(session, wheres=(CariabotModel.organization_code == device.organization_code, ~CariabotModel.is_deleted))
            if not cariabot:
                wheres.append(1 != 1)
            cariabot_columns = await CariabotColumn.fetch_all(session,
                                                              wheres=(CariabotColumn.cariabot_id == cariabot.id, ~CariabotColumn.is_deleted, CariabotColumn.column_type == 'external'),
                                                              orders=CariabotColumn.rank)
            column_ids = [v.id for v in cariabot_columns]
            wheres.append(CariabotColumnService.column_id.in_(column_ids))
        wheres.append(~CariabotColumnService.is_deleted)

        data = await CariabotColumnService.fetch_all(session, wheres=wheres, orders=(CariabotColumnService.id))

        return data

    @staticmethod
    async def get_cariabot_voip_list(session, device: Device, sidebar_id=0, name=''):
        """ 获取设备语音通话列表
        :param session:
        :param device:
        :param sidebar_id:
        :param name:
        :return:
        """
        ret_data = []
        # 判断当前设备的角色
        if device.role == 'user':
            # 用户端查自定义的语音通话列表
            wheres = list()
            if sidebar_id:
                wheres.append(CariabotColumnService.column_id == sidebar_id)
            else:
                cariabot = await CariabotModel.fetch_one(session, wheres=(CariabotModel.organization_code == device.organization_code, ~CariabotModel.is_deleted))
                if not cariabot:
                    wheres.append(1 != 1)
                cariabot_columns = await CariabotColumn.fetch_all(session, wheres=(CariabotColumn.cariabot_id == cariabot.id, ~CariabotColumn.is_deleted, CariabotColumn.column_type == 'voip'))
                column_ids = [v.id for v in cariabot_columns]
                wheres.append(CariabotColumnService.column_id.in_(column_ids))
            if name:
                wheres.append(CariabotColumnService.name.like(f'%{name}%'))
            wheres.append(~CariabotColumnService.is_deleted)

            data = await CariabotColumnService.fetch_all(session, wheres=wheres, orders=(CariabotColumnService.rank))
            ret_data = [v.dict('code', 'name', 'rank') for v in data]
        elif device.role == 'server':
            # 服务端查有房间号的设备列表
            data = await Zeus.get_device_comm_list(device.dev_id, name)
            ret_data = data
        else:
            pass

        return ret_data


if __name__ == '__main__':
    from project.lib.common import Session
    db = Session()
    data = CariabotService.get_cariabot_info(db, organization_code=14)
    print(data)